
#ifndef __DEFERRED_BASE_H__
#define __DEFERRED_BASE_H__

/******************************************************************************\
*
* Deferred depth
*
\******************************************************************************/

half4 EncodedDeferredDepth(float depth)
{
	return half4(depth,depth,depth,depth);
}

float DecodeSceneDepthProj(sampler2D DepthSampler, float4 ScreenTexCoord )
{
	float fDeviceDepth = tex2Dproj(DepthSampler, ScreenTexCoord).x;
	// scale back to full range
	return fDeviceDepth * DepthRange.y;
}

float DecodeSceneDepth(sampler2D DepthSampler, float2 ScreenTexCoord )
{
	float fDeviceDepth = tex2D(DepthSampler, ScreenTexCoord).x;
	// scale back to full range
	return fDeviceDepth * DepthRange.y;
}

half3 EncodeDeferredNormal(half3 normal)
{
	return normal * 0.5h + 0.5h;
}

half3 DecodeSceneNormal(half3 normal)
{
	return normal*2 -1;
}

/*
 */
half4 setDeferredDepth(float distance,half volumetric) {
	half3 deferred;
	distance = sqrt(distance) * 8388608.0f;
	deferred.x = floor(distance * (1.0f / 65536.0f));
	distance -= deferred.x * 65536.0f;
	deferred.y = floor(distance * (1.0f / 256.0f));
	distance -= deferred.y * 256.0f;
	deferred.z = floor(distance);
	deferred = half3(127.0f,255.0f,255.0f) - deferred;
	#ifndef MULTISAMPLE_0
		deferred.x += volumetric * 128.0f;
		return half4(deferred * (1.0f / 255.0f),1.0f);
	#else
		return half4(deferred * (1.0f / 255.0f),volumetric);
	#endif
}

/*
 */
float getDeferredDepth(half4 deferred) {
	float3 factor = float3(16711680.0f / 8388608.0f,65280.0f / 8388608.0f,255.0f / 8388608.0f);
	#ifndef MULTISAMPLE_0
		deferred.x -= floor(deferred.x * (510.0f / 256.0f)) * (128.0f / 255.0f);
	#endif
	float distance = 1.0f - dot(deferred.xyz,factor);
	return distance * distance;
}

half getDeferredVolumetric(half4 deferred) {
	#ifndef MULTISAMPLE_0
		return floor(deferred.x * (510.0f / 256.0f));
	#else
		return deferred.w;
	#endif
}

/******************************************************************************\
*
* Deferred color
*
\******************************************************************************/

/*
 */
half4 setDeferredColor(half3 color,half glow) {
	return half4(color,glow * (1.0f / 16.0f));
}

/*
 */
half3 getDeferredColor(half4 deferred) {
	return deferred.xyz;
}

half getDeferredGlow(half4 deferred) {
	return deferred.w * 16.0f;
}

/******************************************************************************\
*
* Deferred normal
*
\******************************************************************************/

/*
 */
half4 setDeferredNormal(half3 normal,half power) {
	return half4(normal * 0.5f + 0.5f,power * (1.0f / 64.0f));
}

/*
 */
half3 getDeferredNormal(half4 deferred) {
	return deferred.xyz * 2.0f - 1.0f;
}

half getDeferredSpecular(half4 deferred) {
	return deferred.w * 64.0f;
}

/******************************************************************************\
*
* Deferred parallax
*
\******************************************************************************/

/*
 */
half4 setDeferredParallax(half2 offset) {
	half4 deferred;
	offset = saturate(offset * 0.25f + 0.5f) * 65535.0f;
	deferred.xz = floor(offset * (1.0f / 256.0f));
	offset -= deferred.xz * 256.0f;
	deferred.yw = floor(offset);
	return deferred * (1.0f / 255.0f);
}

/*
 */
half2 getDeferredParallax(half4 deferred) {
	if(deferred.x == 0.0f) return half2(0.0f,0.0f);
	half2 factor = half2(65280.0f / 65535.0f,255.0f / 65535.0f);
	return half2(dot(deferred.xy,factor),dot(deferred.zw,factor)) * 4.0f - 2.0f;
}

#endif /* __DEFERRED_BASE_H__ */
